﻿package com.cilico.single.utils;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
//import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
import java.util.Map.Entry;


import android.app.Activity;

/**
 * 
 * @author lv.xiangan
 *
 */
public class PreferenceDB extends RmsDatabase {
	
	/**
	 * 缓存一个RMS记录
	 */
	private static class RmsRecord {
		private String name_;
		private String value_;

		public RmsRecord(String name, String value) {
			name_ = name;
			value_ = value;
		}

		public void setValue(String value) {
			value_ = value;
		}

		public String name() {
			return name_;
		}

		public String value() {
			return value_;
		}
	}
	
	private Hashtable<String, RmsRecord> recHash_;

	/**
	 * Save entire record hash to RMS when the app quits.
	 */
	void save() throws Exception {
		try {
			// Always delete current database before rewriting it.
			deleteDB();
			// open();
			for (Enumeration<RmsRecord> e = recHash_.elements(); e.hasMoreElements();) {
				saveOneRecord((RmsRecord) e.nextElement());
			}
		} catch (Exception e) {
		}
	}

	private void saveOneRecord(RmsRecord record) throws Exception {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(baos);
		byte[] rec;
		try {
			dos.writeUTF(record.name());
			dos.writeUTF(record.value());
			rec = baos.toByteArray();
		} catch (Exception ignored) {
			Utils.printOutToConsole("Failed to write record " + record.name() + " value " + record.value());
			Utils.printOutToConsole("PreferenceDB-saveOneRecord-ignored:" + ignored);
			return;
		} finally {
			try {
				dos.close();
			} catch (Exception e1) {
				Utils.printOutToConsole("PreferenceDB-saveOneRecord-e1:" + e1);
			}
			try {
				baos.close();
			} catch (Exception e2) {
				Utils.printOutToConsole("PreferenceDB-saveOneRecord-e2:" + e2);
			}
		}
		if (store_.getAll().size() < rec.length) {
			throw (new Exception("RMS存储空间不足！"));
		} else {
			store_.edit().putString(new String(rec), new String(rec));
			Utils.printOutToConsole("RMS saved " + record.name() + " " + record.value());
		}
	}

	/**
	 * Load contents of the store into memory.
	 */
	PreferenceDB(Activity app_, String dbname) throws Exception {
		super(app_, dbname);
		recHash_ = new Hashtable<String, RmsRecord>();
	}

	/**
	 * Read all records, and if we have duplicate records in the store, delete the whole store since it's corrupted.
	 */
	@SuppressWarnings("unchecked")
	public void init() throws Exception {
		try {
			// XXX If we can't even traverse the record store, don't do anything and don't raise an exception.
			// 取得存储单元中的所有存储内容
			Map<String, ?> map = store_.getAll();
			if (map == null)
				// Store is empty.
				return;
			map.clear();
			try {
				Iterator<?> iter = map.entrySet().iterator();
				Map.Entry<String, Object> enter;
				String key, value;
				if (null != iter) {
					while (iter.hasNext()) {
						enter = (Entry<String, Object>) iter.next();
						key = enter.getKey().toString();
						value = enter.getValue().toString();
						RmsRecord record = (RmsRecord) recHash_.get(key);
						if (record != null) {
							record.setValue(value);
							Utils.printOutToConsole("*** ERROR *** duplicate record: key " + key);
						} else {
							record = new RmsRecord(key, value);
							recHash_.put(key, record);
							Utils.printOutToConsole("get record: key " + key + " value " + value);
						}
					}
				}
			} finally {
				try {
				} catch (Exception ignored1) {
					Utils.printOutToConsole("PreferenceDB-init-ignored1:" + ignored1.toString());
				}
			}
		} catch (Exception ex) {
			Utils.printOutToConsole("PreferenceDB-init-ex:" + ex.toString());
		}
	}

	/**
	 * Read RMS hash table and return record as a byte array. After reading, remove the record from hash to preserve
	 * memory and to prevent writing out-of-date data to RMS.
	 */
	public String readAndDestroy(String name) {
		RmsRecord record = (RmsRecord) recHash_.get(name);
		if (record == null) {
			return null;
		} else {
			recHash_.remove(name);
			return record.value();
		}
	}

	/**
	 * Read String value from hashtable
	 */
	public String readValue(String key) {
		RmsRecord record = (RmsRecord) recHash_.get(key);
		if (record == null)
			return null;
		else
			return record.value();
	}

	/**
	 * if there has to been a value in hashtable whose key includes name,it will sort history once more.
	 */
	private void sortHistory(String[] keys, String key, String name) {

		int j = key.indexOf("&");
		if (j >= 0) {
			RmsRecord valueTemp;
			String nameTemp;
			int id;
			int addID = Integer.parseInt(key.substring(j + 1));
			for (int t = 0; t < keys.length; t++) {
				String keyTemp = keys[t];
				valueTemp = readRmsRecord(keyTemp);
				int index = keyTemp.indexOf("&");
				nameTemp = keyTemp.substring(0, index).trim();
				id = Integer.parseInt(keyTemp.substring(index + 1));
				if (id > addID) {
					recHash_.remove(keyTemp);
					valueTemp.name_ = nameTemp.concat("&").concat(String.valueOf(id - 1));
					recHash_.put(nameTemp.concat("&").concat(String.valueOf(id - 1)), valueTemp);
				}
			}

			valueTemp = readRmsRecord(key);
			recHash_.remove(key);
			valueTemp.name_ = name.concat("&").concat(String.valueOf(keys.length - 1));
			recHash_.put(name.concat("&").concat(String.valueOf(keys.length - 1)), valueTemp);
		}
	}

	/**
	 * Read RmsRecord value from hashtable
	 */
	public RmsRecord readRmsRecord(String key) {
		return (RmsRecord) recHash_.get(key);
	}

	/**
	 * Read all keys in Hashtable.
	 */
	public String[] readKeys() {
		Enumeration<String> enumeration = recHash_.keys();
		Vector<String> keys = new Vector<String>();
		String keystrs[] = null;

		while (enumeration.hasMoreElements()) {
			String string = null;
			string = (String) enumeration.nextElement();
			keys.addElement(string);
		}

		keystrs = new String[keys.size()];
		for (int i = 0; i < keys.size(); i++) {
			keystrs[i] = (String) keys.elementAt(i);
		}
		keys.removeAllElements();
		return keystrs;
	}


	/**
	 * If the key exists, we update an existing record; otherwise write a new record.
	 */
	public void write(String name, String value) throws Exception {
		// RmsRecord record = (RmsRecord) recHash_.get(name);
		// if (record == null) {
		// record = new RmsRecord(name, value);
		// recHash_.put(record.name(), record);
		// } else {
		// record.setValue(value);
		// }
		// save();
		save(name, value);
	}

	/**
	 * If it limits the length of record,use this method.Now it is only used to save channels history.
	 */
	public void write(String name, String value, boolean limited, int length) throws Exception {
		if (limited) {
			Utils.printOutToConsole("Add key: " + name + " value: " + value);
			int i = 0;
			int j = 0;
			String keys[] = readKeys();
			if (length > 0 && recHash_.size() < length) {
				for (i = 0; i < keys.length; i++) {
					String key = keys[i];
					int t = key.indexOf("&");
					String temp = "";
					if (t >= 0)
						temp = key.substring(0, t);
					if (temp.equals(name)) {
						sortHistory(keys, key, name);
						return;
					}
				}
				write(name.concat("&").concat(String.valueOf(recHash_.size())), value);
			} else if (length > 0 && recHash_.size() == length) {

				for (i = 0; i < keys.length; i++) {
					String key = keys[i];
					int t = key.indexOf("&");
					String temp = "";
					if (t >= 0)
						temp = key.substring(0, t);
					if (temp.equals(name)) {
						sortHistory(keys, key, name);
						return;
					}
				}

				for (i = 0; i < keys.length; i++) {
					String key = keys[i];
					j = key.indexOf("&");
					if (j >= 0) {
						String index = key.substring(j + 1);
						j = Integer.parseInt(index);
						if (j == 0) {
							recHash_.remove(key);
							break;
						}
					}
				}
				keys = readKeys();
				for (i = 0; i < keys.length; i++) {
					String key = keys[i];
					j = key.indexOf("&");
					if (j >= 0) {
						String index = key.substring(j + 1);
						String nam = key.substring(0, j);
						j = Integer.parseInt(index);
						if (j > 0) {
							j--;
							RmsRecord record = (RmsRecord) recHash_.get(key);
							recHash_.remove(key);
							record.name_ = nam.concat("&").concat(String.valueOf(j));
							recHash_.put(nam.concat("&").concat(String.valueOf(j)), record);
						}
					}
				}
				write(name.concat("&").concat(String.valueOf(length - 1)), value);
				keys = readKeys();
				for (i = 0; i < keys.length; i++) {
					String key = keys[i];
					RmsRecord record = (RmsRecord) recHash_.get(key);
					Utils.printOutToConsole("Key: " + key + " Value: " + record.value());
				}
			} else if (length > 0 && recHash_.size() > length) {

				int overlength = recHash_.size() - length - 1;
				while (overlength >= 0) {
					for (i = 0; i < keys.length; i++) {
						String key = keys[i];
						j = key.indexOf("&");
						if (j >= 0) {
							String index = key.substring(j + 1);
							j = Integer.parseInt(index);
						}
						if (j == overlength) {
							recHash_.remove(key);
							overlength--;
							break;
						}
					}
				}
			}
		} else
			write(name, value);
	}
}
